﻿#region Apache 2.0 License header

//   Copyright 2012 Lesley van Zijl
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License. 

#endregion

using System.Reflection;
using System.Reflection.Emit;
using FavourObjects.ForwardBuilders;

namespace FavourObjects.Extensions
{
    /// <summary>
    /// Extension methods for TypeNuilder, used for building favour objects specific builders.
    /// </summary>
    internal static class TypeBuilderExtensions
    {
        /// <summary>
        /// Creates a ForwardMethodBuilder used to create the methods that are needed in the 
        /// generated assembly to call non-public methods.
        /// </summary>
        /// <typeparam name="TTargetClass">Type of the class that is targetted by this method builder</typeparam>
        /// <param name="typeBuilder">The typebuilder that is used to generate the assembly type.</param>
        /// <param name="methodBuilder">The method builder that is used to generate the method to reach the non-public method</param>
        /// <param name="targetMethod">The method on the targetclass that the generated method should call.</param>
        /// <param name="innerObjectField">A reference to a field which contains the instance of the target class.</param>
        /// <returns>A method builder specialized to generate forwarding methods.</returns>
        public static ForwardMethodBuilder<TTargetClass> CreateForwardMethodBuilder<TTargetClass>(
            this TypeBuilder typeBuilder,
            MethodBuilder methodBuilder, MethodInfo targetMethod, FieldInfo innerObjectField)
            where TTargetClass : class
        {
            return new ForwardMethodBuilder<TTargetClass>(methodBuilder, targetMethod, innerObjectField);
        }

        /// <summary>
        /// Creates a ForwardPropertyBuilder used to create the properties that are needed in the 
        /// generated assembly to call non-public fields.
        /// </summary>
        /// <typeparam name="TTargetClass">Type of the class that is targetted by this property builder.</typeparam>
        /// <param name="typeBuilder">The typebuilder that is used to generate the assembly type.</param>
        /// <param name="propertyBuilder">The property builder that is used to generate the property to reach the non-public field.</param>
        /// <param name="targetField">The field on the targetclass that the generated method should call.</param>
        /// <param name="innerObjectField">A reference to a field which contains the instance of the target class.</param>
        /// <returns>A property builder specialized to generate forwarding properties that target fields.</returns>
        public static ForwardPropertyToFieldBuilder<TTargetClass> CreateForwardPropertyToFieldBuilder<TTargetClass>(
            this TypeBuilder typeBuilder,
            PropertyBuilder propertyBuilder, FieldInfo targetField, FieldInfo innerObjectField)
            where TTargetClass : class
        {
            return new ForwardPropertyToFieldBuilder<TTargetClass>(typeBuilder, propertyBuilder, targetField,
                                                                   innerObjectField);
        }

        /// <summary>
        /// Creates a ForwardPropertyBuilder used to create the properties that are needed in the 
        /// generated assembly to call non-public properties.
        /// </summary>
        /// <typeparam name="TTargetClass">Type of the class that is targetted by this property builder.</typeparam>
        /// <param name="typeBuilder">The typebuilder that is used to generate the assembly type.</param>
        /// <param name="propertyBuilder">The property builder that is used to generate the property to reach the non-public property.</param>
        /// <param name="targetProperty">The property on the targetclass that the generated method should call.</param>
        /// <param name="innerObjectField">A reference to a field which contains the instance of the target class.</param>
        /// <returns>A method builder specialized to generate forwarding properties.</returns>
        public static ForwardPropertyToPropertyBuilder<TTargetClass> CreateForwardPropertyToPropertyBuilder
            <TTargetClass>(this TypeBuilder typeBuilder,
                           PropertyBuilder propertyBuilder, PropertyInfo targetProperty, FieldInfo innerObjectField)
            where TTargetClass : class
        {
            return new ForwardPropertyToPropertyBuilder<TTargetClass>(typeBuilder, propertyBuilder, targetProperty,
                                                                      innerObjectField);
        }
    }
}